package com.wulis.provider.basic.service.impl;

import static com.wulis.common.constant.GlobalConstant.TOKEN_PREFIX;
import static com.wulis.common.model.enums.HttpStatusEnum.PHONE_NUMBER_EXISTS;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.beans.BeanUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wulis.common.exception.BusinessException;
import com.wulis.common.model.enums.DeletedStateEnum;
import com.wulis.common.support.BaseServiceImpl;
import com.wulis.provider.basic.mapper.UserInfoMapper;
import com.wulis.provider.basic.model.dto.InsertUserDto;
import com.wulis.provider.basic.model.dto.QueryUserPageDto;
import com.wulis.provider.basic.model.dto.UpdateUserDto;
import com.wulis.provider.basic.model.entity.UserInfo;
import com.wulis.provider.basic.model.vo.QueryUserListVo;
import com.wulis.provider.basic.model.vo.QueryUserPageVo;
import com.wulis.provider.basic.model.vo.QueryUserVo;
import com.wulis.provider.basic.service.UserInfoService;
import com.wulis.provider.authority.model.bo.UpdateAccountBo;
import com.wulis.provider.authority.service.AccountRoleService;
import com.wulis.provider.authority.service.AccountService;

import lombok.AllArgsConstructor;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

/**
 * 基础信息管理：用户表 Service实现类
 *
 * @author WuliBao
 * @date 2020-05-21
 */
@Slf4j
@Service
@AllArgsConstructor
public class UserInfoServiceImpl extends BaseServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
    
    private final UserInfoMapper userInfoMapper;
    
    private final AccountService accountService;
    
    private final AccountRoleService accountRoleService;
    
    @Resource
    private final RedisTemplate<String, String> redisTemplate;
    
    /**
     * WEB:查询用户列表(分页)
     *
     * @param queryUserPageDto queryUserPageDto
     * @return IPage
     */
    @Override
    public IPage<QueryUserPageVo> queryUserPage(@NonNull QueryUserPageDto queryUserPageDto) {
        Page<QueryUserPageVo> page = new Page<>(queryUserPageDto.getPageNumber(), queryUserPageDto.getPageSize());
        return userInfoMapper.queryUserPage(page,
            queryUserPageDto.getAccount(),
            queryUserPageDto.getUserName(),
            queryUserPageDto.getPhoneNumber(),
            queryUserPageDto.getOrganizationId(),
            queryUserPageDto.getDepartmentId(),
            queryUserPageDto.getEnable());
    }
    
    /**
     * WEB:查询用户列表(根据部门ID)
     *
     * @param departmentId departmentId
     * @return List
     */
    @Override
    public List<QueryUserListVo> queryUserList(@NonNull Long departmentId) {
        return userInfoMapper.queryUserList(departmentId);
    }
    
    /**
     * WEB:查询用户
     *
     * @param id id
     * @return QueryUserVo
     */
    @Override
    public QueryUserVo queryUser(@NonNull Long id) {
        return userInfoMapper.queryUser(id);
    }
    
    /**
     * WEB:新增用户
     *
     * @param insertUserDto insertUserDto
     * @return Integer
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer insertUser(@NonNull InsertUserDto insertUserDto) {
        // 插入账号
        Long accountId = accountService
            .insertAccount(insertUserDto.getAccount(), insertUserDto.getPassword(), insertUserDto.getEnable());
        UserInfo userInfo = new UserInfo();
        BeanUtils.copyProperties(insertUserDto, userInfo);
        userInfo.setAccountId(accountId);
        int insert;
        try {
            insert = userInfoMapper.insert(userInfo);
        }
        catch (DuplicateKeyException e) {
            // 判断是否是已删除用户的恢复操作
            synchronized (this) {
                QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(UserInfo::getAccountId, accountId);
                UserInfo user = userInfoMapper.selectOne(queryWrapper);
                // 如果是被删除用户，恢复其账号信息
                if (user != null && DeletedStateEnum.IS_DELETED.value().equals(user.getDeleted())) {
                    BeanUtils.copyProperties(insertUserDto, user);
                    user.setAccountId(accountId).setDeleted(DeletedStateEnum.NOT_DELETED.value());
                    try {
                        return userInfoMapper.updateById(user);
                    }
                    catch (DuplicateKeyException de) {
                        throw new BusinessException(PHONE_NUMBER_EXISTS);
                    }
                }
            }
            throw new BusinessException(PHONE_NUMBER_EXISTS);
        }
        // 插入角色信息
        accountRoleService.insertAccountRole(accountId, insertUserDto.getRoleIds());
        return insert;
    }
    
    /**
     * WEB:修改用户
     *
     * @param updateUserDto updateUserDto
     * @return 账号ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer updateUser(@NonNull UpdateUserDto updateUserDto) {
        UserInfo userInfo = userInfoMapper.selectById(updateUserDto.getId());
        if (userInfo == null) {
            return 0;
        }
        // 修改账号
        UpdateAccountBo updateAccountBo = new UpdateAccountBo();
        BeanUtils.copyProperties(updateUserDto, updateAccountBo);
        if (!updateAccountBo.isEmpty()) {
            updateAccountBo.setId(userInfo.getAccountId());
            accountService.updateAccount(updateAccountBo);
        }
        UserInfo updateUser = new UserInfo();
        BeanUtils.copyProperties(updateUserDto, updateUser);
        int update;
        try {
            update = userInfoMapper.updateById(updateUser);
        }
        catch (DuplicateKeyException e) {
            throw new BusinessException(PHONE_NUMBER_EXISTS);
        }
        // 修改角色信息
        if (updateUserDto.getRoleIds() != null) {
            accountRoleService.updateAccountRole(userInfo.getAccountId(), updateUserDto.getRoleIds());
        }
        // 删除登录状态
        redisTemplate.delete(TOKEN_PREFIX + userInfo.getId());
        return update;
    }
    
    /**
     * WEB:删除用户
     *
     * @param userId userId
     * @return Integer
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer deleteUser(@NonNull Long userId) {
        UserInfo userInfo = userInfoMapper.selectById(userId);
        if (userInfo == null) {
            return 0;
        }
        // 删除账号
        accountService.deleteAccount(userInfo.getAccountId());
        // 删除用户信息
        UserInfo deleteUser = new UserInfo();
        deleteUser.setId(userId);
        deleteUser.setDeleted(DeletedStateEnum.IS_DELETED.value());
        int delete = userInfoMapper.updateById(deleteUser);
        // 删除角色信息
        accountRoleService.deleteAccountRole(userInfo.getAccountId());
        // 删除登录状态
        redisTemplate.delete(TOKEN_PREFIX + userInfo.getId());
        return delete;
    }
}
